const timeThresholds = 60000;//达到一分钟即把日志上传
const countThresholds = 20;//20条把日志上传到服务端
const receiveTraceUrl = '/xsb/ability/trace/h5receiveTraceNew';//服务端上报采集日志URL
const traceBusiUrl = '/xsb/ability/trace/h5qryTraceBusiInfo';//获取需要无埋点采集的菜单列表--ald_trace_busi_conf
let traceSeqUrl = '/xsb/ability/common/h5getSeqByName?name=seq_ald_trace';//查询trace主键seq
import CallChainLog from '@/base/log/pointLessLog/index.js'
import Storage from '@/base/storage'
import { delStorage,getTime,getStorage } from './pointLessLog/util/util';
import ClientJs from '@/base/clientjs'
/***
 * 无埋点调用链
 */
class PointLessLog {
    //构造函数
    constructor(_vue,_axios){
        this._vue = _vue;
        this._axios = _axios;
        this.logSwitchData = [];//日志开关数组
        this.logSwitchMap = {};//日志开关map
        this.loginTraceId = '';//登录traceId
        this.commonData = {busiSeq:'',telnum:'',busiType:''};//公共参数 业务traceId、busitype（菜单编号） 用户手机号、操作员手机号、地市、操作员工号
        this.uinfo = Storage.session.get('userInfo');//当前登录用户的信息
        this._initSwitch();//初始化开关数据
    }
    //1、获取无埋点调用链接的总开关
    //2、获取需要无埋点采集的菜单列表
    //3、获取登录总traceId
    //4、初始化无埋点插件
    _initSwitch(){
        let url = '/xsb/ability/businessLimit/h5QryBusiPermission';
        let param = {
            'busiType':'call_chain_v2' //调用链开关
        };
        //1、获取无埋点调用链接的总开关
        this._axios.post(url,param).then((res)=>{
            if(res.data.retCode == '0'){//调用链日志开
                //2、获取需要无埋点采集的菜单列表 "data":["20000033"]=》[{"privId":"20000033","type":(1:采集，透传，2：不采集，透传)}]
                this._axios.post(traceBusiUrl).then(res => {
                    let {retCode,data} = res.data;
                    if(retCode == 0){//服务端返回成功
                        if(data && data.length >0){//判断有需要无埋点采集的业务菜单
                            this.setSwitchData(data);//封装开关字典数据
                            //3、获取登录总traceId
                            this.getTraceSeq().then(res => {
                                let {retCode,data} = res.data;
                                if(retCode == '0'){
                                    this.loginTraceId = data;//服务端返回登录流水号
                                    this.commonData.loginTraceId = data;
                                    //4、初始化无埋点插件
                                    this.initLogPlugin();
                                }
                            })
                        }

                    }
                })
            }
        });
    }
    //将数组转成 纯菜单号的数组和map
    /**
     * 封装开关字典
     * @param 后台返回的数据对象 data：[{"privId":"20000033","type":(1:采集，透传，2：不采集，透传)},{"privId":"20000044","type":(1:采集，透传，2：不采集，透传)}]
     * 转成logSwitchData:["20000033","20000044"]
     * 转成logSwitchMap：{"20000033":1,"20000044":2}
     */
    setSwitchData(data){
        this.logSwitchMap = {};//是否采集离线数据的开头
        this.logSwitchData = [];//开关配置数组
        for(let i = 0; i < data.length; i++){
            let item = data[i];
            this.logSwitchData.push(item.privId);
            this.logSwitchMap[item.privId] = item.type;
        }
    }

    //获取采集流水号(traceId)
    async getTraceSeq(){
        return this._axios.post(traceSeqUrl)
    }
    //4、初始化无埋点插件
    initLogPlugin(){
        let u = this.uinfo;
        this._setChainCommonData('imei',u.imei==void 0 ?'':u.imei);//imei号
        this._setChainCommonData('operId',u.crmId);//操作员工号
        this._setChainCommonData('serverNum',u.servNumber);//操作员号码
        this._setChainCommonData('region',u.region);//地市

        var OPTIONS = {
            useImgSend: false,
            selector: 'input,textArea',
            loginTraceId:this.loginTraceId,//登录总流水
            postUrl:receiveTraceUrl,//上报日志的服务端路径
            classTag:'',//主动埋点class名称, 自动埋点时请配置空字符串
            sizeLimit: countThresholds,  //操作数据超过指定条目时自动上报
            timeThresholds:timeThresholds,//达到时间阀值后自动上报
            commonAcData:this.commonData,
            logSwitchMap:this.logSwitchMap,
            axios:this._axios
        }
        window._vue.use(CallChainLog, OPTIONS)
    }
    //调用链顺序节点处理
    dealSpanNodeOrder(cData){
        // console.log(cData)
        let spanNode = cData.spanNode || 1;
        let nextSpanNode = cData.nextSpanNode || spanNode;//1.1 1.2
        let tmp = Math.floor(nextSpanNode);//取整数部分
        if(tmp == spanNode){
            nextSpanNode = nextSpanNode + 0.1;
        } else {
            nextSpanNode = spanNode + 0.1;//整数部分不一样，表示新动作的调用链
        }
        try {
            nextSpanNode = Math.round(nextSpanNode * 10) / 10;//保留一位小数，防止浮点数运算的精度问题
        } catch (error) {
            console.error(error);
        }
        cData.nextSpanNode = nextSpanNode;
        return nextSpanNode;
    }
    //设置
    addHeaderCfg(cfg){
        let cData = this.commonData;
        if(!this.loginTraceId || !cData.busiSeq){//如果没有获取到登录流水则不加这些头标识
            return;
        }
        if(cfg.url && ~cfg.url.indexOf(receiveTraceUrl)){//离线上报请求不加额外头信息
            return;
        }
        let u = this.uinfo;
        if(cData.spanNode == '0'){//点击动作之前的获取token等异步请求不做采集处理
            return;
        }
        let nextSpanNode = this.dealSpanNodeOrder(cData)
        let psid = getStorage('pageSpanId') || '';//页面dom元素
        cfg.headers.spanId = psid;
        cfg.headers.traceId = cData.busiSeq;//业务流水
        cfg.headers.nextSpanNode = nextSpanNode;
        let baggage = {
            region: u.region,//地市编码
            busiType: cData.busiType,//业务类型，取菜单编码
            imei: u.imei==void 0 ?'':u.imei,//imei号
            operId: u.crmId, //操作员工号
            serverNum: u.servNumber,//操作员号码
            telnum: cData.telnum, //客户手机号
            loginId:this.loginTraceId
        };
        cfg.headers.baggage = JSON.stringify(baggage);
    }
    //设置调用链插件的公用参数，如用户手机号、业务流水、菜单ID
    _setChainCommonData(key,value){
        if(value && key && this.loginTraceId){//key和value都不为空的情况,并且已经有登录流水
            let param = {}
            param[key] = value;
            Object.assign(this.commonData,param);
            try{
                CallChainLog.setCommenData(this.commonData);
            }catch(e){
                console.error(e);
            }
        }
    }
    //获取调用链数据
    getClientChainParam(telnum){
        let u = this.uinfo;
        let cData = this.commonData;
        //判断登录流水和业务流水
        if(!this.loginTraceId || !cData.busiSeq){//如果没有获取到登录流水则返回空
            return {};
        }
        let nextSpanNode = this.dealSpanNodeOrder(cData)
        let spanId = getStorage('pageSpanId') || '';//页面dom元素
        if(telnum){//如果传了手机号
            this._setChainCommonData('telnum',telnum);
        }
        //baggage 属性
        let baggage = {
            region: u.region,//地市编码
            busiType: cData.busiType,//业务类型，取菜单编码
            imei: u.imei==void 0 ?'':u.imei,//imei号
            operId: u.crmId, //操作员工号
            serverNum: u.servNumber,//操作员号码
            telnum: cData.telnum, //客户手机号
            loginId:this.loginTraceId
        };
        let chainParam = {
            spanId:spanId,
            traceId:cData.busiSeq,//业务流水,
            nextSpanNode:nextSpanNode,
            baggage:baggage
        };
        return chainParam;
    }
    //设置用户手机号
    setChainTelnum(telnum,curDom,$callChainLog){
        this._setChainCommonData('telnum',telnum);
        if(curDom && $callChainLog){
            $callChainLog.collectClick(curDom);
        }
    }
    //采集客户端回调信息
    setChainClientCb(curDom,$callChainLog,extraParam){
        if(curDom && $callChainLog){
            $callChainLog.collectClientCbInfo(curDom,extraParam);
        }
    }
    //获取当前系统时间
    getCurentTime(){
        return getTime();
    }
    //设置业务编码，即菜单编号
    setChainBusiType(busiType){
        if(!busiType){
            return;
        }
        delStorage('pageSpanId');
        this._clearBusiSeq('busiSeq');
        //判断当前busiType不在采集范围内
        if(this.logSwitchData.indexOf(busiType) == -1){
            return;
        }
        //设置调用链需要采集的菜单编号
        this._setChainCommonData('busiType',busiType);
        this._setChainCommonData('spanNode','0');
        //获取该菜单的业务traceId
        this.getTraceSeq().then(res => {
            let {retCode,data} = res.data;
            if(retCode == '0'){
                //服务端返回流水号
                this._setChainCommonData('busiSeq',data);
            }
        }).catch(e=>{
            console.info(e);
        })
    }
    //清除业务流水，场景：点击菜单都会生成唯一的业务流水，当点击的菜单不在采集范围内，应当把上一个业务流水清除掉
    _clearBusiSeq(key){
        CallChainLog.clearCommenData(key);
    }
    //设置业务流水号
    setChainBusiSeq(busiSeq){
        if(!busiSeq){//如果为空，则表示清空
            CallChainLog.clearCommenData('busiSeq');
        }
        this._setChainCommonData('busiSeq',busiSeq);
    }
}


//
const pointMixin = {
    data(){return {
    }},
    methods:{
        //调用客户端拉起页面 paramObj对象的传参见ClientJs.openWebKitWithStatus
        /**
         * openWebKitWithStatus('/url',{title:'专区',titleFlag : '1'})
         */
        openWebKitWithStatus(url,paramObj,clickDom ='拉起外围页面') {

            let params = {
                title : '',
                titleFlag : '0',//默认没有标题
                screenType : '',
                param: '',
                hasRightBtn : '',
                rightIcon : '',
                rightJs:'',
                hasRightBtn1 : '',
                rightIcon1: '',
                rightJs1:'',
                transformData:{
                    openViewTime:this.$pointLesslog && this.$pointLesslog.getCurentTime(), //打开外围页面的时间
                    clickDomNode:clickDom//定义打开外围页面的dom节点描述
                }//需要客户端透传返回的参数
            };
            let spanId = '';
            let openUrl = url;

            let chain = this.$callChainLog;//调用链对象
            console.info('chain:',chain);
            if (chain && chain.installed){//调用链对象存在
                chain.collectClick(clickDom);
                spanId = getStorage('pageSpanId');
            }
            if(spanId) {//如果没有spanId,表示从菜单拉起的外围菜单，没有采集点击动作
                openUrl = openUrl + `&pageId=${spanId}`;//应客户要求，外围链接拼接spanId
            }
            console.info('openUrl:',openUrl);
            params.url = openUrl;
            Object.assign(params,paramObj);
            //客户端新增打开页面的方法，打开页面后回调JS侧，返回打开页面的状态
            if((window.WebViewFunc && window.WebViewFunc.openWebKitWithStatus) || (window.webkit && window.webkit.messageHandlers.openWebKitWithStatus)){
                params.callBackFun = 'openWebKitCbFn';//新增回调方法
                ClientJs.openWebKitWithStatus(openUrl,params);
            } else {
                openUrl = encodeURIComponent(openUrl);
                ClientJs.openWebKitNew(openUrl,params);
                let retJson = {"retCode":"0","retMsg":"sucess"};
                retJson.transformData = params.transformData;
                openWebKitCbFn(JSON.stringify(retJson));//旧版未升级默认都返回“成功打开”
            }

        },
    },
    mounted(){
        window['openWebKitCbFn'] = (res)=>{
            console.info(res,'==openWebKitCbFn');
            let resObj = JSON.parse(res);
            let {retCode,retMsg,transformData} = resObj;
            //状态码 状态描述  开始时间
            let param = {statusCode: retCode, errorMsg:retMsg,startTime:transformData.openViewTime};
            let pointDom = 'span.noop_openwebview_' + transformData.clickDomNode;
            this.$pointLesslog && this.$pointLesslog.setChainClientCb(pointDom,this.$callChainLog,param);
        }
    }
}

export {PointLessLog,pointMixin};
